package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
)

func main() {
	p := &Parser{}
	p.Parse("1 + 3 + 3 + 3 - 3")
	res := p.Result().Interpret()
	expect := 7
	if res != expect {
		log.Fatalf("error: expect %d get %d", expect, res)
	}

	fmt.Printf("except: %d, got %d", expect, res)
}

/*
解释器模式，用于解决需要解释语言中的句子或表达式的问题。以下是一些可以在 程序中使用解释器模式的真实场景：

1.处理配置文件
许多应用程序使用配置文件来指定应用程序的行为方式。这些配置文件可以用 YAML 或 JSON 等 DSL 编写。解释器可用于解析这些配置文件并以应用编程语言对象的形式向应用程序提供配置信息。
2.模板引擎
模板引擎处理模板和一组变量以产生输出。模板是DSL的一个例子，可以使用Interpreter来解析和处理模板。
3.数学表达式计算器
数学表达式是我们日常都能接触到的，使用了一种特定领域语言语法书写语句或者叫表达式的实例
这些表达式在程序里可以使用解释器模式进行解析和解释。例如，计算器应用程序可以使用解释器来解析和评估用户输入的数学表达式。
4.自然语言处理
在更高级的情况下，解释器模式可用于解析和解释自然语言，不过这通常会涉及想机器学习这样的更复杂的技术。
虽然解释器模式可以用来解决这些问题，但它并不总是最好的解决方案。对于复杂的语言，使用特定的解析库或工具或其他设计模式可能更有效。
*/

/*
解释器模式中的关键组件有：

表达式接口：表示抽象语法树的元素并定义解释表达式的方法。
具体表达式：实现表达式接口的结构，表示语言语法的各种规则或元素。
上下文对象：用于保存解释过程中所需的任何必要信息或状态。
Parser 或 Builder：负责根据输入表达式构建抽象语法树的组件。
*/

type Expression interface {
	Interpret() int
}

type NumberExpression struct {
	val int
}

func (n *NumberExpression) Interpret() int {
	return n.val
}

type AdditionExpression struct {
	left, right Expression
}

func (n *AdditionExpression) Interpret() int {
	return n.left.Interpret() + n.right.Interpret()
}

type SubtractionEcpression struct {
	left, right Expression
}

func (s *SubtractionEcpression) Interpret() int {
	return s.left.Interpret() - s.right.Interpret()
}

type Parser struct {
	exp   []string
	index int
	pre   Expression
}

func (p *Parser) Parse(exp string) {
	p.exp = strings.Split(exp, " ")

	for {
		if p.index >= len(p.exp) {
			return
		}
		switch p.exp[p.index] {
		case "+":
		case "-":
		default:

		}
	}
}

func (p *Parser) newNumberExpression() Expression {
	v, _ := strconv.Atoi(p.exp[p.index])
	p.index++
	return &NumberExpression{
		val: v,
	}
}

func (p *Parser) newAdditionExpression() Expression {
	p.index++
	return &AdditionExpression{
		left:  p.pre,
		right: p.newNumberExpression(),
	}
}

func (p *Parser) newSubtractionExpression() Expression {
	p.index++
	return &SubtractionEcpression{
		left:  p.pre,
		right: p.newNumberExpression(),
	}
}

func (p *Parser) Result() Expression {
	return p.pre
}

/*
在程序中使用解释器模式的目标是： 定义特定于领域的语言及其语法，使用 AST（抽象语法树）表示语言中的表达式或句子，好让程序能够根据一组规则或操作解释或评估表达式

最后我们再来列举一下解释器模式的优缺点。 使用解释器模式的优点是：

关注点分离：该模式将解释逻辑与数据表示分开。
可扩展性：可以通过添加新的表达式结构轻松地扩展模式。
可重用性：解释器模式可以在需要解析或解释特定领域语言的不同项目或上下文中重用。
使用解释器模式的缺点是：

复杂性：随着语法规则数量的增加，模式会变得复杂。
性能：对于大型表达式，抽象语法树的递归遍历可能很慢。
*/
